import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 增强版多线程色子游戏
 * 带有图形界面和更丰富的游戏功能
 */
public class EnhancedDiceGame extends JFrame {

    // 游戏常量定义
    private static final int MAX_PLAYERS = 8;  // 最大玩家数量
    private static final int MIN_PLAYERS = 2;  // 最小玩家数量
    // 玩家颜色数组，用于区分不同玩家
    private static final Color[] PLAYER_COLORS = {
            new Color(255, 102, 102), // 红色
            new Color(102, 178, 255), // 蓝色
            new Color(102, 255, 178), // 绿色
            new Color(255, 178, 102), // 橙色
            new Color(178, 102, 255), // 紫色
            new Color(255, 255, 102), // 黄色
            new Color(102, 255, 255), // 青色
            new Color(204, 102, 255)  // 紫红色
    };

    // Swing组件声明
    private JPanel mainPanel;          // 主面板
    private JPanel controlPanel;       // 控制面板
    private JPanel playerPanel;        // 玩家信息面板
    private JPanel resultPanel;        // 结果面板
    private JButton startButton;      // 开始按钮
    private JTextField[] nameFields;  // 玩家名字输入框数组
    private JSpinner playerCountSpinner; // 玩家数量选择器
    private JLabel statusLabel;       // 状态标签
    private JLabel winnerLabel;       // 获胜者标签
    private JLabel[] diceLabels;      // 骰子结果显示标签数组

    // 游戏相关变量
    private ExecutorService executor;  // 线程池
    private Player[] players;          // 玩家数组
    private AtomicInteger completedPlayers; // 已完成投掷的玩家计数器(原子操作)

    // 构造函数
    public EnhancedDiceGame() {
        initComponents();  // 初始化组件
        setupLayout();     // 设置布局
    }

    // 初始化所有Swing组件
    private void initComponents() {
        setTitle("多线程色子游戏");  // 设置窗口标题
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  // 设置关闭操作
        setSize(800, 600);  // 设置窗口大小
        setLocationRelativeTo(null);  // 居中显示

        // 初始化主面板
        mainPanel = new JPanel(new BorderLayout(10, 10));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        // 初始化控制面板
        controlPanel = new JPanel(new GridLayout(3, 2, 5, 5));
        controlPanel.setBorder(BorderFactory.createTitledBorder("游戏设置"));

        // 玩家数量选择器
        playerCountSpinner = new JSpinner(new SpinnerNumberModel(MIN_PLAYERS, MIN_PLAYERS, MAX_PLAYERS, 1));
        controlPanel.add(new JLabel("玩家数量:"));
        controlPanel.add(playerCountSpinner);

        // 开始按钮
        startButton = new JButton("开始游戏");
        startButton.addActionListener(new StartButtonListener());  // 添加事件监听器
        controlPanel.add(startButton);

        // 状态标签
        statusLabel = new JLabel("等待游戏开始...", JLabel.CENTER);
        statusLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
        controlPanel.add(statusLabel);

        // 玩家面板
        playerPanel = new JPanel();
        playerPanel.setLayout(new BoxLayout(playerPanel, BoxLayout.Y_AXIS));
        playerPanel.setBorder(BorderFactory.createTitledBorder("玩家信息"));

        // 结果面板
        resultPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
        resultPanel.setBorder(BorderFactory.createTitledBorder("游戏结果"));
        winnerLabel = new JLabel(" ", JLabel.CENTER);
        winnerLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
        resultPanel.add(winnerLabel);

        // 将各面板添加到主面板
        mainPanel.add(controlPanel, BorderLayout.NORTH);
        mainPanel.add(new JScrollPane(playerPanel), BorderLayout.CENTER);
        mainPanel.add(resultPanel, BorderLayout.SOUTH);

        add(mainPanel);  // 将主面板添加到窗口
        updatePlayerFields();  // 更新玩家输入字段
    }

    // 设置布局和事件监听
    private void setupLayout() {
        // 玩家数量变化监听器
        playerCountSpinner.addChangeListener(e -> updatePlayerFields());
    }

    // 根据玩家数量更新玩家输入字段
    private void updatePlayerFields() {
        playerPanel.removeAll();  // 清空玩家面板
        int count = (Integer) playerCountSpinner.getValue();  // 获取当前玩家数量
        nameFields = new JTextField[count];  // 初始化名字输入框数组
        diceLabels = new JLabel[count];     // 初始化骰子标签数组

        // 为每个玩家创建输入面板
        for (int i = 0; i < count; i++) {
            JPanel playerFieldPanel = new JPanel(new BorderLayout(5, 5));
            playerFieldPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            playerFieldPanel.setBackground(PLAYER_COLORS[i % PLAYER_COLORS.length].brighter());

            // 玩家标签
            JLabel playerLabel = new JLabel("玩家 " + (i + 1) + ":");
            playerLabel.setFont(new Font("微软雅黑", Font.BOLD, 12));

            // 名字输入框和骰子结果标签
            nameFields[i] = new JTextField("玩家" + (i + 1));
            diceLabels[i] = new JLabel("等待投掷...", JLabel.CENTER);
            diceLabels[i].setFont(new Font("微软雅黑", Font.BOLD, 14));

            // 将组件添加到玩家面板
            playerFieldPanel.add(playerLabel, BorderLayout.WEST);
            playerFieldPanel.add(nameFields[i], BorderLayout.CENTER);
            playerFieldPanel.add(diceLabels[i], BorderLayout.EAST);

            playerPanel.add(playerFieldPanel);
        }

        // 刷新面板
        playerPanel.revalidate();
        playerPanel.repaint();
    }

    // 开始按钮事件监听器
    private class StartButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            startButton.setEnabled(false);  // 禁用开始按钮
            playerCountSpinner.setEnabled(false);  // 禁用玩家数量选择器
            winnerLabel.setText(" ");  // 清空获胜者标签
            statusLabel.setText("游戏进行中...");  // 更新状态

            int playerCount = (Integer) playerCountSpinner.getValue();  // 获取玩家数量
            players = new Player[playerCount];  // 初始化玩家数组
            completedPlayers = new AtomicInteger(0);  // 初始化完成玩家计数器

            // 创建玩家对象
            for (int i = 0; i < playerCount; i++) {
                String name = nameFields[i].getText().trim();
                if (name.isEmpty()) {
                    name = "玩家" + (i + 1);  // 默认名字
                }
                players[i] = new Player(name, i);  // 创建玩家实例
            }

            // 创建线程池
            executor = Executors.newFixedThreadPool(playerCount);

            // 提交玩家任务到线程池
            for (Player player : players) {
                executor.submit(player);
            }

            // 启动结果检查线程
            new Thread(new ResultChecker()).start();

            executor.shutdown();  // 关闭线程池(不再接受新任务)
        }
    }

    // 玩家类，实现Runnable接口
    private class Player implements Runnable {
        private final String name;  // 玩家名字
        private final int index;    // 玩家索引
        private int diceValue;      // 骰子值
        private final Random random; // 随机数生成器

        public Player(String name, int index) {
            this.name = name;
            this.index = index;
            this.random = new Random();
        }

        @Override
        public void run() {
            try {
                // 模拟思考时间(随机延迟)
                Thread.sleep(random.nextInt(1000) + 500);

                // 投掷骰子(1-6)
                diceValue = random.nextInt(6) + 1;

                // 在事件调度线程中更新UI
                SwingUtilities.invokeLater(() -> {
                    diceLabels[index].setText(name + " 投出了: " + diceValue);
                    diceLabels[index].setForeground(PLAYER_COLORS[index % PLAYER_COLORS.length].darker());
                });

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();  // 恢复中断状态
            } finally {
                completedPlayers.incrementAndGet();  // 增加完成玩家计数
            }
        }

        // 获取骰子值
        public int getDiceValue() {
            return diceValue;
        }

        // 获取玩家名字
        public String getName() {
            return name;
        }
    }

    // 结果检查器，检查所有玩家是否完成并确定获胜者
    private class ResultChecker implements Runnable {
        @Override
        public void run() {
            try {
                // 等待所有玩家完成
                while (completedPlayers.get() < players.length) {
                    Thread.sleep(100);  // 每隔100ms检查一次
                }

                // 确定获胜者
                Player winner = determineWinner(players);

                // 在事件调度线程中更新UI
                SwingUtilities.invokeLater(() -> {
                    statusLabel.setText("游戏结束!");
                    winnerLabel.setText("获胜者: " + winner.getName() + " (点数: " + winner.getDiceValue() + ")");
                    winnerLabel.setForeground(PLAYER_COLORS[getPlayerIndex(winner) % PLAYER_COLORS.length]);

                    // 高亮显示获胜者
                    for (int i = 0; i < players.length; i++) {
                        if (players[i] == winner) {
                            diceLabels[i].setFont(new Font("微软雅黑", Font.BOLD, 16));
                        }
                    }

                    // 重新启用控件
                    startButton.setEnabled(true);
                    playerCountSpinner.setEnabled(true);
                });

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();  // 恢复中断状态
            }
        }

        // 获取玩家索引
        private int getPlayerIndex(Player player) {
            for (int i = 0; i < players.length; i++) {
                if (players[i] == player) {
                    return i;
                }
            }
            return -1;
        }
    }

    // 确定获胜者(点数最大的玩家)
    private Player determineWinner(Player[] players) {
        Player winner = players[0];  // 假设第一个玩家是获胜者
        for (int i = 1; i < players.length; i++) {
            if (players[i].getDiceValue() > winner.getDiceValue()) {
                winner = players[i];  // 更新获胜者
            }
        }
        return winner;
    }

    // 主方法
    public static void main(String[] args) {
        // 在事件调度线程中创建和显示GUI
        SwingUtilities.invokeLater(() -> {
            try {
                // 设置系统外观
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                e.printStackTrace();
            }

            // 创建并显示游戏窗口
            EnhancedDiceGame game = new EnhancedDiceGame();
            game.setVisible(true);
        });
    }
}